/*
 *   Copyright (c) 2018. 刘路 All rights reserved
 *   版权所有 刘路 并保留所有权利 2018.
 *   ===============================================================
 *   这不是一个自由软件！您只能在不用于商业目的的前提下对程序代码进行修改和
 *   使用。不允许对程序代码以任何形式任何目的的再发布。如果项目发布携带作者
 *   认可的特殊 LICENSE 则按照 LICENSE 执行，废除上面内容。请保留原作者信息。
 *   ================================================================
 *   刘路（feedback@zhoyq.com）于 2018. 创建
 *   http://zhoyq.com
 */

package com.zhoyq.helper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 依赖注入工具类
 * {@link Service}
 * @author 刘路
 */
public class Ioc {

    private static Logger log = LoggerFactory.getLogger(Ioc.class);

    private static final Ioc me = new Ioc();

    private Ioc() {
    }

    public static Ioc getIoc() {
        return me;
    }

    /**
     * 零配置！！！
     * 每次获取都是新的对象
     */
    private Map<String, Class<?>> bean = new HashMap<>();
    /**
     * 获取single单例对象
     */
    private Map<String, Object> singleBean = new HashMap<>();

    /**
     * 添加bean
     * @param calss
     * @param isSingle
     * @return
     */
    public Ioc add(Class<?> calss, boolean isSingle) {
        add(calss.getName(), calss, isSingle);
        return this;
    }

    public Ioc add(String calss, boolean isSingle) {
        try {
            add(calss, Class.forName(calss), isSingle);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return this;
    }

    public Ioc add(String key, String calss, boolean isSingle) {
        try {
            add(key, Class.forName(calss), isSingle);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return this;
    }

    public Ioc add(String key, Class<?> calss, boolean isSingle) {
        if (isSingle) {
            try {
                singleBean.put(key, calss.getDeclaredConstructor().newInstance());
            } catch (InstantiationException e) {
                log.warn(e.getMessage());
            } catch (IllegalAccessException e) {
                log.warn(e.getMessage());
            } catch (NoSuchMethodException e) {
                log.warn(e.getMessage());
            } catch (InvocationTargetException e) {
                log.warn(e.getMessage());
            }
        } else {
            bean.put(key, calss);
        }

        return this;
    }

    public Ioc addPackage(String pack, boolean isSingle,boolean isRecursive) {

        List<Class<?>> list = ClassHelper.getClassList(pack, isRecursive);
        for(Class<?> calss : list){
            Service s = calss.getAnnotation(Service.class);
            if (s != null) {
                if (StringHelper.isEmpty(s.value())) {
                    add(calss, isSingle);
                } else {
                    add(s.value(), calss, isSingle);
                }
            }
        }

        return this;
    }

    public static Object getBean(String key) {

        if (getIoc().bean.containsKey(key)) {
            try {
                return getIoc().bean.get(key).getDeclaredConstructor().newInstance();
            } catch (InstantiationException | IllegalAccessException
                    | NoSuchMethodException | InvocationTargetException e) {
                log.warn(e.getMessage());
                return null;
            }
        }

        return getIoc().singleBean.get(key);
    }

    public static Object getBean(Class<?> key) {
        return getBean(key.getName());
    }

    public boolean start() {
        return true;
    }

    public boolean stop() {
        bean.clear();
        return true;
    }

}